# C:/Python27/TextResuming/word_weighting.py
# This is word_weighting file
# Author : @ismailsunni

from  __future__ import division
import math
import text as text
import operator
import util as util


#################### start of NP_term ####################
def get_dict_fraction(list_term, dict_NP_term):
	'''Return a dictionary contains term and its fraction.'''
	
	dict_term = {}
	for term in set(list_term):
		if dict_NP_term[term] != 0:
			dict_term[term] = list_term.count(term) / dict_NP_term[term]
		else:
			dict_term[term] = 0

	return dict_term

def get_segmentation_by_NP_term(base_list_term, dict_NP_term, list_index_in_segment, num_top):
	'''Return a new list of list term after joining.'''

	# Create list of terms
	list_of_term = []
	for list_index in list_index_in_segment:
		new_list_term = []
		for index in list_index:
			new_list_term.extend(base_list_term[index])
		list_of_term.append(new_list_term)

	# Create list of num top term
	list_of_top_term = []
	list_dict_term_fration = []
	for terms in list_of_term:
		dict_term_fraction = get_dict_fraction(terms, dict_NP_term)
		list_dict_term_fration.append(dict_term_fraction)
		top = int(math.ceil(num_top * len(set(terms))))

		top_terms =util.convert_list_of_tuple_to_dictionary(util.sort_dictionary_by_value(dict_term_fraction, True, top)).keys()
		list_of_top_term.append(top_terms)

	# Calculate similarity value
	list_of_sim_value = []
	i = 0
	while i < len(list_of_top_term) - 1:
		sim_value = get_similarity_by_set(set(list_of_top_term[i]), set(list_of_top_term[i+1]))
		print i, set(list_of_top_term[i]), set(list_of_top_term[i+1])
		list_of_sim_value.append(sim_value)
		i += 1
	print 'list_of_sim_value', list_of_sim_value
	index_max_sim = list_of_sim_value.index(max(list_of_sim_value))

	# Join segment
	retval = []
	i = 0
	while i < (len(list_of_top_term)):
		if i == index_max_sim:
			new_index = []
			new_index.extend(list_index_in_segment[i])
			new_index.extend(list_index_in_segment[i+1])

			retval.append(new_index)

		elif i == index_max_sim + 1:
			pass

		else:
			retval.append(list_index_in_segment[i])

		i += 1
	
	# return [retval, list_of_sim_value]
	return {'retval':retval, 'list_of_sim_value':list_of_sim_value, 'list_dict_term_fration' : list_dict_term_fration }

#################### end of NP_term ####################

#################### Start of TF-IDF ####################
def get_TF(word, bag_of_word):
	'''Return a TF value of a word from bag_of_word.

		bag_of_word is a list of word.'''
		
	return bag_of_word.count(word) / len(bag_of_word)

def get_IDF(word, list_of_list_of_word):
	'''Return a IDF value of a word from list_of_list_of_word.
		
		With normalization.'''
		
	num_occur = 0
	for list_of_word in list_of_list_of_word:
		if (word in list_of_word):
			num_occur += 1
	if num_occur == 0:
		return 0
	return math.log(len(list_of_list_of_word) / num_occur)

def get_TF_IDF(word, bag_of_word, list_of_list_of_word):
	'''Return Tf.Idf value.'''
	
	return get_TF(word, bag_of_word) * get_IDF(word, list_of_list_of_word)

#################### Start of similarity ####################
def get_length_vector(list_word, dict_TF_IDF):
	'''Return lenght of vector of list_word.'''

	retval = 0
	for word in list_word:
		retval += (util.get_from_dictionary(word, dict_TF_IDF) * util.get_from_dictionary(word, dict_TF_IDF) )

	return math.sqrt(retval)

# Weight similarity
def get_weight_similarity(list_index_1, list_index_2, list_of_list_term):
	'''Get weight similarity of 2 cluster.'''

	# Variables
	retval = 0
	list_set_term = []
	set_term_index_2 = set()
	num_index = len(list_index_1)

	# Create set of term of list_index_2
	for index in list_index_2:
		set_term_index_2 |= set(list_of_list_term[index])

	# Create list of set of term in each segment/index in list_index_1
	for index in list_index_1:
		term_set = set(list_of_list_term[index])
		list_set_term.append(term_set)

	# Calculate weight similarity
	i = num_index
	for set_term in list_set_term:
		weight = get_similarity_by_set(set_term, set_term_index_2)
		weight = (1 / (i * (i + 1))) * weight
		# weight = (1 / num_index) * weight
		retval += weight
		i -= 1
	
	return retval

# Set
def get_similarity_by_set(set_A, set_B):
	'''Return a similarity value according set.'''

	num_intersect = len(set_A & set_B)
	num_union = len(set_A | set_B)

	if num_union == 0:
		return 0
	else:
		return num_intersect / num_union

# Tf-Idf
def get_similarity_by_TF_IDF(list_word_1, list_word_2, dict_TF_IDF):
	'''Get cosine similarity.'''
	
	numerator = 0
	for word in list_word_1:
		if (word in list_word_2):
			numerator += util.get_from_dictionary(word, dict_TF_IDF) * util.get_from_dictionary(word, dict_TF_IDF)
	v1 = get_length_vector(list_word_1, dict_TF_IDF)
	v2 = get_length_vector(list_word_2, dict_TF_IDF)
	
	if (v1 == 0 or v2 == 0):
		return 0
	else:
		return numerator / (v1 * v2)

if __name__ == '__main__':
	pass	
